<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- 
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License. 
-->
<html>
<head>
    <link type="text/css" rel="stylesheet" href="https://struts.apache.org/css/default.css">
    <style type="text/css">
        .dp-highlighter {
            width:95% !important;
        }
    </style>
    <style type="text/css">
        .footer {
            background-image:      url('https://cwiki.apache.org/confluence/images/border/border_bottom.gif');
            background-repeat:     repeat-x;
            background-position:   left top;
            padding-top:           4px;
            color:                 #666;
        }
    </style>
    <link href='https://struts.apache.org/highlighter/style/shCoreStruts.css' rel='stylesheet' type='text/css' />
    <link href='https://struts.apache.org/highlighter/style/shThemeStruts.css' rel='stylesheet' type='text/css' />
    <script src='https://struts.apache.org/highlighter/js/shCore.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushPlain.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushXml.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJava.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushJScript.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushGroovy.js' type='text/javascript'></script>
    <script src='https://struts.apache.org/highlighter/js/shBrushBash.js' type='text/javascript'></script>
    <script type="text/javascript">
        SyntaxHighlighter.defaults['toolbar'] = false;
        SyntaxHighlighter.all();
    </script>
    <script type="text/javascript" language="javascript">
        var hide = null;
        var show = null;
        var children = null;

        function init() {
            /* Search form initialization */
            var form = document.forms['search'];
            if (form != null) {
                form.elements['domains'].value = location.hostname;
                form.elements['sitesearch'].value = location.hostname;
            }

            /* Children initialization */
            hide = document.getElementById('hide');
            show = document.getElementById('show');
            children = document.all != null ?
                    document.all['children'] :
                    document.getElementById('children');
            if (children != null) {
                children.style.display = 'none';
                show.style.display = 'inline';
                hide.style.display = 'none';
            }
        }

        function showChildren() {
            children.style.display = 'block';
            show.style.display = 'none';
            hide.style.display = 'inline';
        }

        function hideChildren() {
            children.style.display = 'none';
            show.style.display = 'inline';
            hide.style.display = 'none';
        }
    </script>
    <title>Struts 2 JUnit Plugin Tutorial</title>
</head>
<body onload="init()">
<table border="0" cellpadding="2" cellspacing="0" width="100%">
    <tr class="topBar">
        <td align="left" valign="middle" class="topBarDiv" align="left" nowrap>
            &nbsp;<a href="home.html">Home</a>&nbsp;&gt;&nbsp;<a href="tutorials.html">Tutorials</a>&nbsp;&gt;&nbsp;<a href="struts-2-junit-plugin-tutorial.html">Struts 2 JUnit Plugin Tutorial</a>
        </td>
        <td align="right" valign="middle" nowrap>
            <form name="search" action="https://www.google.com/search" method="get">
                <input type="hidden" name="ie" value="UTF-8" />
                <input type="hidden" name="oe" value="UTF-8" />
                <input type="hidden" name="domains" value="" />
                <input type="hidden" name="sitesearch" value="" />
                <input type="text" name="q" maxlength="255" value="" />
                <input type="submit" name="btnG" value="Google Search" />
            </form>
        </td>
    </tr>
</table>

<div id="PageContent">
    <div class="pageheader" style="padding: 6px 0px 0px 0px;">
        <!-- We'll enable this once we figure out how to access (and save) the logo resource -->
        <!--img src="/wiki/images/confluence_logo.gif" style="float: left; margin: 4px 4px 4px 10px;" border="0"-->
        <div style="margin: 0px 10px 0px 10px" class="smalltext">Apache Struts 2 Documentation</div>
        <div style="margin: 0px 10px 8px 10px"  class="pagetitle">Struts 2 JUnit Plugin Tutorial</div>

        <div class="greynavbar" align="right" style="padding: 2px 10px; margin: 0px;">
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14811898">
                <img src="https://cwiki.apache.org/confluence/images/icons/notep_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Edit Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/editpage.action?pageId=14811898">Edit Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">
                <img src="https://cwiki.apache.org/confluence/images/icons/browse_space.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Browse Space"></a>
            <a href="https://cwiki.apache.org/confluence/pages/listpages.action?key=WW">Browse Space</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14811898">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_page_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add Page"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createpage.action?spaceKey=WW&fromPageId=14811898">Add Page</a>
            &nbsp;
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14811898">
                <img src="https://cwiki.apache.org/confluence/images/icons/add_blogentry_16.gif"
                     height="16" width="16" border="0" align="absmiddle" title="Add News"></a>
            <a href="https://cwiki.apache.org/confluence/pages/createblogpost.action?spaceKey=WW&fromPageId=14811898">Add News</a>
        </div>
    </div>

    <div class="pagecontent">
        <div class="wiki-content">
            <div id="ConfluenceContent"><p>When creating unit tests for your Struts 2 application you'll want to be able to test certain aspects of the action class that normally require the action to be running within a Servlet container and the Struts 2 interceptors to have executed.&#160; For example if your Struts 2 action class includes a validate method that checks the values of the instance fields populated by the user's input on a Struts 2 form, you need the interceptors to have run that get the user's form field input out of request scope and assign the form field values to the appropriate instance fields.</p>

<p>Struts 2 provides a JUnit plugin library that makes it easier to develop unit tests for testing your Struts 2 action classes.&#160; This tutorial will provide an example of how to use the Struts 2 JUnit plugin.</p>

<div class="confluence-information-macro confluence-information-macro-note"><span class="aui-icon aui-icon-small aui-iconfont-warning confluence-information-macro-icon"></span><div class="confluence-information-macro-body"><p>This tutorial assumes the reader knows how to create a Struts 2 application and how to write unit tests using JUnit.</p></div></div>


<p>To use the Struts 2 JUnit plugin, you'll need to have the plugin's Jar file on your application's class path.&#160; If you're using Maven you can add this dependency to your pom.xml.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Struts 2 JUnit Plugin Dependency</b></div><div class="codeContent panelContent pdl">
<pre class="brush: xml; gutter: false; theme: Default" style="font-size:12px;">
&lt;dependency&gt;
    &lt;groupId&gt;org.apache.struts&lt;/groupId&gt;
    &lt;artifactId&gt;struts2-junit-plugin&lt;/artifactId&gt;
    &lt;version&gt;STRUTS_VERSION&lt;/version&gt;
&lt;/dependency&gt;

</pre>
</div></div>

<p>Of course replace STRUTS_VERSION with the current Struts 2 version number.</p>

<p>For this tutorial we'll use the following Struts 2 ActionSupport class.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>AccountAction.java</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
public class AccountAction extends ActionSupport {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = Logger.getLogger( AccountAction.class.getName() );

	private Account accountBean;

	public String execute(){

		return SUCCESS;

	}

	public void validate(){

		logger.debug("In method validate. accountBean's state is " + accountBean );

		if ( accountBean.getUserName().length() == 0 ){

			addFieldError( "accountBean.userName", "User name is required." );

		}

		if ( accountBean.getUserName().length() &lt; 5 ) {

			addFieldError( "accountBean.userName", "User name must be at least 5 characters long." );

		}

		if ( accountBean.getUserName().length() &gt; 10 ) {

			addFieldError( "accountBean.userName", "User name cannot be at more than 10 characters long." );

		}


	}

	public Account getAccountBean() {
		return accountBean;
	}

	public void setAccountBean(Account accountBean) {
		this.accountBean = accountBean;
	}

}


</pre>
</div></div>

<p>The above action class is called after a user enters information on a create account form.  Struts takes the user's input on the form fields and uses those values to populate the state of the Account object (accountBean).</p>

<p>Then the validate method is executed to check the values of the accountBean's instance fields against certain business rules (for example the length of the username cannot be more than 10).</p>

<p>To test the validate method we can use the Struts 2 JUnit plugin to simulate the Servlet container and Struts 2 framework. Our Junit test class just needs to extend the StrutsTestCase.  The StrutsTestCase class is part of the Strut 2 JUnit Plugin library.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>JUnit Test Case For Struts Action Class</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
public class TestAccountActionUsingStrutsTestCase extends StrutsTestCase {

    public void testUserNameErrorMessage() throws Exception {

    	request.setParameter("accountBean.userName", "Bruc");
    	request.setParameter("accountBean.password", "test");

    	ActionProxy proxy = getActionProxy("/createaccount");

    	AccountAction accountAction = (AccountAction) proxy.getAction();

        proxy.execute();

        assertTrue("Problem There were no errors present in fieldErrors but there should have been one error present", accountAction.getFieldErrors().size() == 1);
		assertTrue("Problem field account.userName not present in fieldErrors but it should have been",
				accountAction.getFieldErrors().containsKey("accountBean.userName") );

    }

    public void testUserNameCorrect() throws Exception {

    	request.setParameter("accountBean.userName", "Bruce");
    	request.setParameter("accountBean.password", "test");

    	ActionProxy proxy = getActionProxy("/createaccount");

    	AccountAction accountAction = (AccountAction) proxy.getAction();

        String result = proxy.execute();

        assertTrue("Problem There were errors present in fieldErrors but there should not have been any errors present", accountAction.getFieldErrors().size() == 0);
        assertEquals("Result returned form executing the action was not success but it should have been.", "success", result);

    }

}


</pre>
</div></div>

<p>The request object above is a MockHttpServletRequest provided by the StrutsTestCase class.  We can use this mock Servlet Request object to set values on the request scope as if the user had typed those values into a Struts 2 form input fields.  Those values will then be available to the Struts 2 action class.</p>

<p>We then create a proxy of the createaccount action.  This action is defined in struts.xml as follows.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>struts.xml</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
&lt;action name="createaccount" class="edu.ku.it.si.struts2_junit_example.action.AccountAction"&gt;
	&lt;result&gt;/thankyou.jsp&lt;/result&gt;
	&lt;result name="input"&gt;/createaccount.jsp&lt;/result&gt;
&lt;/action&gt;

</pre>
</div></div>

<p>When we run this test, the proxy of the createaccount action will be executed which will cause the Struts 2 interceptors to fire (so the request scope values will be assigned to the correct Action class instance fields) and then the validate method will be executed.</p>

<p>The two test methods above are used to test the action's validate method when the username doesn't meet the business requirements (too few characters) and when the username does meet the business requirements.</p>

<p>Note in the second test method where we have the statement: </p>

<p><code>String result = proxy.execute();</code></p>

<p>This statement stores the result returned by the Action class (e.g. "success") which we can then use in an assert statement to test if the result is what it should be.</p>

<p><code>assertEquals("Result returned form executing the action was not success but it should have been.", "success", result);</code></p>

<h3 id="Struts2JUnitPluginTutorial-TestingaStrutsactionagainstacustomStrutsconfigurationfile">Testing a Struts action against a custom Struts configuration file</h3>

<p>Override <code>getConfigPath</code> method to return a comma separated list of paths to a configuration file.</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Specify Struts Configuration File Location Example</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">
    @Override
    protected String getConfigPath() {
        return "struts-test.xml";
    }

</pre>
</div></div>

<h3 id="Struts2JUnitPluginTutorial-TestingAStrutsActionWhenUsingSpring">Testing A Struts Action When Using Spring</h3>

<p>If your Struts application is using Spring to manage class relationships and you want test your Struts action class with the Spring container, then have your test class extend <code>StrutsSpringTestCase</code> instead of <code>StrutsTestCase</code>.  </p>

<p>The <code>StrutsSpringTestCase</code> class expects your Spring configuration file to be loaded from <code>classpath:applicationContext.xml</code> (configuration file named applicationContext.xml and in the root of the class path).  If your Spring configuration file has a different name or location, in your test class override method:</p>

<p> <code>protected java.lang.String getContextLocations()</code></p>

<p>For example:</p>

<div class="code panel pdl" style="border-width: 1px;"><div class="codeHeader panelHeader pdl" style="border-bottom-width: 1px;"><b>Specify Spring Configuration File Location Example</b></div><div class="codeContent panelContent pdl">
<pre class="brush: java; gutter: false; theme: Default" style="font-size:12px;">

@Override
public String getContextLocations() {
		
  return "edu/ku/it/si/tutorial/action/TestAccountAction-context.xml";

}

</pre>
</div></div>
</div>
        </div>

        
    </div>
</div>
<div class="footer">
    Generated by CXF SiteExporter
</div>
</body>
</html>
